package com.jinxin.platform.cdacscontrolmgr.event;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jinxin.platform.base.api.annotation.APCOSApiOperation;
import com.jinxin.platform.base.api.annotation.APCOSApiRequest;
import com.jinxin.platform.base.api.annotation.APCOSApiRequests;
import com.jinxin.platform.base.api.constant.APCOSApiConstans;
import com.jinxin.platform.base.common.annotation.RecEvent;
import com.jinxin.platform.base.common.pojo.JsonResult;
import com.jinxin.platform.base.common.support.PlatFormEventListener;
import com.jinxin.platform.cdacscontrolmgr.bean.*;
import com.jinxin.platform.cdacscontrolmgr.bean.bo.CarOrderInfo;
import com.jinxin.platform.cdacscontrolmgr.bean.bo.OptionItem;
import com.jinxin.platform.cdacscontrolmgr.common.Constant;
import com.jinxin.platform.cdacscontrolmgr.common.SysOrgInfo;
import com.jinxin.platform.cdacscontrolmgr.mapper.*;
import com.jinxin.platform.cdacscontrolmgr.redis.CdacscontrolmgrRedisUtil;
import com.jinxin.platform.cdacscontrolmgr.rpc.CdacscontrolmgrRpc;
import com.jinxin.platform.cdacscontrolmgr.service.*;
import com.jinxin.platform.cdacscontrolmgr.utils.*;
import com.jinxin.platform.cdacscontrolmgr.websocket.CdacscontrolmgrWebSocket;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.util.StringUtils;

import javax.websocket.Session;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.*;

/**
 * All rights Reserved, Designed By www.beonelot.com
 *
 * @version: V1.0
 * @Copyright: www.beonelot.com Inc. All rights reserved.
 * @Description：
 * @Date: 2021-02-05
 * @Author: Lingnan
 **/
@Component
@RecEvent(eventType = Constant.MODULE_KEY + "_cdAcsControlmgrReport")
@Slf4j
public class AcsControlmgrCarRecordReportListener implements PlatFormEventListener {
    @Autowired
    private ICdacscontrolkmgrCarInfoService carInfoService;
    @Autowired
    private ICdacsControlmgrProjectBarrierService controlmgrProjectBarrierService;
    @Autowired
    private ICdacscontrolkmgrCarRecordService carRecordService;
    @Autowired
    private ICdacscontrolkmgrCxlfRecordService cxlfRecordService;
    @Autowired
    private CdacscontrolmgrRegistInfoMapper registInfoMapper;
    @Autowired
    private CdacscontrolmgrOwnerMapper ownerMapper;
    @Autowired
    private ICdacscontrolkmgrProjectAccessService projectAccessService;
    @Autowired
    private ICdacscontrolkmgrPersonRecordService personRecordService;
    @Autowired
    private ICdacscontrolkmgrVisitorRecordService visitorRecordService;
    @Autowired
    private PlatformTransactionManager transactionManager;
    @Autowired
    private CdacscontrolmgrUserMapper cdacscontrolmgrUserMapper;
    @Autowired
    private CdacscontrolmgrNoticeMapper cdacscontrolmgrNoticeMapper;
    @Autowired
    private ICdacscontrolmgrProjectService cdacscontrolmgrProjectService;
    @Autowired
    private ICdacscontrolmgrChargeConfigService cdacscontrolmgrChargeConfigService;
    @Autowired
    private CdacscontrolmgrRuledetailMapper cdacscontrolmgrRuledetailMapper;
    @Autowired
    private CdacscontrolmgrOrderMgtMapper cdacscontrolmgrOrderMgtMapper;
    @Autowired
    private CdacscontrolmgrRedisUtil cdacscontrolmgrRedisUtil;
    @Autowired
    private ICdacscontrolmgrCarCategoryService carCategoryService;
    @Value("${platform.upload}")
    private String uploadPath;
    @Autowired
    private CdacscontrolmgrRpc cdacscontrolmgrRpc;
    @Autowired
    private ICdacscontrolmgrOrderInfoService cdacscontrolmgrOrderInfoService;
    @Autowired
    private Cdacscontrolmgr200InfoMapper cdacscontrolmgr200InfoMapper;
    @Autowired
    private CdacscontrolmgrProjectLedContentMapper projectLedContentMapper;
    @Autowired
    private CdacscontrolmgrProjectLedMapper projectLedMapper;
    @Autowired
    private CdacscontrolmgrProjectLcdMapper projectLcdMapper;
    @Autowired
    private CdacscontrolmgrProjectLcdContentMapper projectLcdContentMapper;
    @Autowired
    private CdacscontrolmgrProjectYwpMapper projectYwpMapper;
    @Autowired
    private CdacscontrolmgrCarInsideMapper carInsideMapper;
    private DateTimeFormatter df =
            DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    private ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();

    @APCOSApiOperation(value = Constant.MODULE_KEY + "_cdAcsControlmgrReport",
            description = "监听设备上报广播", infDict = "设备上报", respDemo = "{\"data\":\"上报数据\",\"modules\":\"模块编号集合\"}",
            infType = APCOSApiConstans.INF_TYPE_INSERT)
    @APCOSApiRequests({
            @APCOSApiRequest(name = "data", value = "上报数据", dict = "上报数据", fieldType = APCOSApiConstans.FIELD_TYPE_GN,required = true,
                    dataType = APCOSApiConstans.DATA_TYPE_STR,keyType = APCOSApiConstans.KEY_TYPE_STR,lenth = "2000", remark = "上报数据"),
            @APCOSApiRequest(name = "modules", value = "模块编号集合", dict = "模块编号集合", fieldType = APCOSApiConstans.FIELD_TYPE_GN,required = true,
                    dataType = APCOSApiConstans.DATA_TYPE_STR, keyType = APCOSApiConstans.KEY_TYPE_STR,lenth = "500", remark = "模块编号集合")
    })
    @Override
    //@Transactional(rollbackFor = Exception.class)
    public JsonResult event(Map resultMap) {
        //        {data={"reportMessage":"{\"r2\":\"0\",\"r3\":\"0\",\"r4\":\"��AF6655\",\"r5\":\"1\",\"r6\":\"2021-11-23 17:07:48\",
//        \"r1\":\"000\"}","product_code":"0008d503","serial_num":"0008d5030008d504","account":"1564400000003040",
//        "cmd_id":"6483","cmd_name":"returnivsresult","createTime":1637658415963}, modules=[apcos-cdacscontrolmgr,apcos-cdyardmgr]}
        String upDataStr = JSON.toJSONString(resultMap);
        if (resultMap == null) {
            return JsonResult.ok(AcsControlmgrCarRecordReportListener.class);
        }
        if (!resultMap.containsKey("data") ) {
            return JsonResult.ok(AcsControlmgrCarRecordReportListener.class);
        }
        JSONObject upDataJson = JSONObject.parseObject(upDataStr);
//        String modules = upDataJson.get("modules").toString();
        LocalDateTime localDateTime = LocalDateTime.now();
        log.info("门禁模块上报: " + upDataStr);
        // 只处理自己模块的上报信息
//        if (modules.contains(Constant.MODULE_KEY)) { //车辆识别}
        JSONObject dataJson = upDataJson.getJSONObject("data");
        JSONObject reportMessage = dataJson.getJSONObject("reportMessage");
        String productCode = dataJson.getString("product_code");
        String cmdName = dataJson.getString("cmd_name");
        String serialNum = dataJson.getString("serial_num");
        boolean isYcsb = Constant.CMD_NAME_HAVE_CAR.equals(cmdName);
        boolean isWcsb = Constant.CMD_NAME_STATUS_REPORTING.equals(cmdName);
        if (Constant.CMD_NAME_RETURN_SNAPSHOT.equalsIgnoreCase(cmdName)) {
            // 只处理包序号为000(车牌识别上报的)
            String r1Str = reportMessage.getString("r1");
            if (Constant.IOCTL_RESP_BXH.equals(r1Str)) {
                log.info("门禁管理车辆识别上报: " + upDataStr);
                // 返回的r2是jxLabel存在缓存服务器上，需要base64解码
                String jxLabel = reportMessage.getString("r2");
                CdtwohundredkInfo cdtwohundredkInfo = cdacscontrolmgr200InfoMapper.selectByKey(jxLabel);
                if(cdtwohundredkInfo == null || StringUtils.isEmpty(cdtwohundredkInfo.getParamaValue())){
                    log.error("缓存数据不存在");
                    return JsonResult.error("缓存数据不存在");
                }
                String paramaValue = cdtwohundredkInfo.getParamaValue();
                String carNumber = StringUtil.getCarNum(paramaValue);
                //carNumber = EncodingUtil.hexToString(r4Str,"GBK");//是否需要？
                String path = Constant.UPLOAD_FILE_MIDDLE_PATH + DateUtil.getCurrentDateTimeStr() + ".jpg";
                String filePath = this.uploadPath + path;
                ImageUtils.saveFile(paramaValue, filePath);
                String picturePath = "/upload" + path;
                String province = carNumber.substring(0,1);
                String carNo = carNumber.substring(1).trim();
                CdacscontrolmgrCarRecord carRecord = new CdacscontrolmgrCarRecord();
                carRecord.setMac(serialNum);
                CdacscontrolmgrCxlfRecord cllfRecord = new CdacscontrolmgrCxlfRecord();
                cllfRecord.setPicture(picturePath);
                cllfRecord.setMac(serialNum);
                CdfinanmodOrder order = new CdfinanmodOrder();
                String projectId = null;
                String barrierId = "";
                boolean isComeIn = true; //是否是进场
                HashMap param = new HashMap();
                param.put("carMac", serialNum);
                CdparkmanagerProjectBarrier projectBarrier = controlmgrProjectBarrierService.selectOne(param);
                if (projectBarrier != null) {
                    carRecord.setCarNo(carNumber);
                    cllfRecord.setCarNo(carNumber);
                    String barrierName = projectBarrier.getBarrierName();
                    carRecord.setSignoName(barrierName);
                    cllfRecord.setSignoName(barrierName);
                    Integer barrierDirection = projectBarrier.getBarrierDirection();
                    isComeIn = barrierDirection.equals(Constant.BARRIER_DIRECTION_IN);
                    String direction = barrierDirection.equals(Constant.BARRIER_DIRECTION_IN) ? "进" : "出";
                    carRecord.setDirection(direction);
                    carRecord.setPassTime(localDateTime);
                    cllfRecord.setPassTime(localDateTime);
                    projectId = projectBarrier.getProjectId();
                    carRecord.setProjectId(projectId);
                    cllfRecord.setProjectId(projectId);
                    order.setProId(projectId);
                    order.setParkSite(projectBarrier.getBarrierAddress());
                    barrierId = projectBarrier.getId();
                }
                if (StringUtils.isEmpty(projectId)) {
                    log.info("该设备未添加到项目中");
                    return JsonResult.error("该设备未添加到项目中");
                }
                CdparkmanagerProject projectInfo = cdacscontrolmgrProjectService.selectByKey(projectId);
                if (projectInfo == null || !Constant.PROJECT_TYPE_ACS.equals(projectInfo.getProjectType())) {
                    log.info("门禁项目不存在");
                    return JsonResult.error("门禁项目不存在");
                }
                CdparkmanagerProject newProjectInfo = new CdparkmanagerProject();
                newProjectInfo.setId(projectInfo.getId());
                int carNum = projectInfo.getCarNum() != null ? projectInfo.getCarNum() : Constant.NUM_ZERO;
                Integer surplusCarNum = projectInfo.getSurplusCarNum();
                if(surplusCarNum == null){
                    surplusCarNum = carNum;
                }
                log.info("推送车牌号，在线人员 " + CdacscontrolmgrWebSocket.clients.size());
                Map<String, Session> clients = CdacscontrolmgrWebSocket.clients;
                boolean isCarInside = isCarInside(carNumber, projectId);
                // 如果是进入,判断车辆是否在场内,在场内不允许再进入
                if(isComeIn && isCarInside){
                    sendMsgToScreen(clients,barrierId,Constant.SCREEN_STATUS_BUSY, true,Constant.THE_CAR_NO_RIGHT,
                            carNumber,surplusCarNum,Constant.ZERO,Constant.ZERO,serialNum);
                    log.info("该车辆已在场内");
                    return JsonResult.error("该车辆已在场内");
                }
                // 如果是出,判断车辆是否已进入,不在场内不允许出去
                if(!isComeIn && !isCarInside){
                    sendMsgToScreen(clients,barrierId,Constant.SCREEN_STATUS_BUSY, false,Constant.THE_CAR_NO_RIGHT,
                            carNumber,surplusCarNum,Constant.ZERO,Constant.ZERO,serialNum);
                    log.info("该车辆未进入");
                    return JsonResult.error("该车辆未进入");
                }
                HashMap param2 = new HashMap();
                param2.put("province", province);
                param2.put("carNo", carNo);
                param2.put("flag", "free");
                param2.put("yardId",projectId);
                CdyardmgrCarInfo carInfo = carInfoService.selectOne(param2);
                JsonResult jsonResult;
                String orderId = StringUtil.getUuid();
                DefaultTransactionDefinition def = new DefaultTransactionDefinition();
                def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);//新发起一个事务
                TransactionStatus transaction = transactionManager.getTransaction(def);
                String projectNo = projectInfo.getProjectNo();
                CdxmyyOrderMgt orderMgt = queryOrderMgt(carNumber, projectNo);

                if (carInfo != null || orderMgt != null) { //业主或物业进入
                    // 包时车到期没续费不允许进入
                    if(isComeIn && orderMgt != null &&  !isValidTime(orderMgt)){
                        String msg = "包时车到期没续费不允许进入";
                        log.error(msg);
                        // 发送数据给led和lcd
                        sendMsgToScreen(clients,barrierId,Constant.SCREEN_STATUS_BUSY, true,Constant.THE_CAR_NO_RIGHT,
                                carNumber,surplusCarNum,Constant.ZERO,Constant.ZERO,serialNum);
                        return JsonResult.error(msg);
                    }
                    if(carInfo != null){
                        carRecord.setCategoryId(carInfo.getCategoryId());
                        carRecord.setCategory(carInfo.getCategory());
                    }else {
                        String categoryId = carCategoryService.getTemCarCategoryId(projectInfo.getOrganId());
                        carRecord.setCategoryId(categoryId);
                        carRecord.setCategory(Constant.CAR_TYPE_BAOSHI);
                    }
                    carRecord.setOrderId(orderId);
                    carRecord.setPicture(picturePath);
                    carRecord.setJcfs(Constant.JCFS_NORMAL);
                    jsonResult = carRecordService.saveOrUpdate(carRecord,isComeIn);
                } else {
                    // 访客车辆来访
                    // 临停车(访客车辆) 需要去查询访客登记表
                    HashMap param3 = new HashMap();
                    param3.put("carnoOrPhone", carNumber);
                    param3.put("projectId", projectId);
                    param3.put("visitDate", DateUtil.getCurrentDayYMD("yyyy-MM-dd"));
                    CdacscontrolmgrRegistInfo registInfo = registInfoMapper.selectOne(param3);
                    if(registInfo == null){
                        //访客登记信息也没有的车辆不允许进入
                        String msg = "无访客登记信息车辆不允许进入";
                        log.error(msg);
                        // 发送数据给led和lcd
                        sendMsgToScreen(clients,barrierId,Constant.SCREEN_STATUS_BUSY,isComeIn,Constant.THE_CAR_NO_RIGHT,
                                carNumber,surplusCarNum,Constant.ZERO,Constant.ZERO,serialNum);
                        // 5秒后回到空闲状态
//                            String finalBarrierId = barrierId;
//                            boolean finalIsComeIn = isComeIn;
//                            Integer finalSurplusCarNum = surplusCarNum;
//                            executorService.schedule(() -> sendMsgToScreen(clients, finalBarrierId,Constant.SCREEN_STATUS_FREE, finalIsComeIn,"",
//                                    "", finalSurplusCarNum,Constant.ZERO,Constant.ZERO,serialNum), Constant.NUM_FIVE, TimeUnit.SECONDS);
                        return JsonResult.error(msg);
                    }
                    String visitTime = registInfo.getVisitDate() + " " + registInfo.getComeinTime() + " - " + registInfo.getLeaveTime();
                    cllfRecord.setVisitTime(visitTime);
                    cllfRecord.setOwner(registInfo.getOwnerName());
                    cllfRecord.setPhone(registInfo.getOwnerPhone());
                    // 更新访客登记表状态为已到访
                    registInfo.setStatus(Constant.REGIST_INFO_STATUS_FINISHED);
                    registInfo.setVisitTime(LocalDateTime.now());
                    registInfoMapper.updateByKey(registInfo);
                    cllfRecord.setOrderId(orderId);
                    cllfRecord.setJcfs(Constant.JCFS_NORMAL);
                    jsonResult = cxlfRecordService.saveOrUpdate(cllfRecord,isComeIn);
                }
                boolean isBaoshiChe = isBaoshiChe(carNumber, projectNo);
                String type = carInfo != null ? carInfo.getCategory() : Constant.CAR_TYPE_TEMP;
                if(isBaoshiChe){
                    order.setCarType(Constant.CAR_TYPE_BAOSHI);
                    type = Constant.CAR_TYPE_BAOSHI;
                }else {
                   order.setCarType(type);
                }
                if (jsonResult.getSuccess()) {
                    String yardName = projectInfo.getProjectName();
                    String recordId = (String) jsonResult.getData();
                    // 推送车牌识别的消息给云坐席
                    Integer managerFlag = projectInfo.getManagerFlag();
                    log.info("门禁推送车牌号，在线人员:" + CdacscontrolmgrWebSocket.clients.toString());
                    if(managerFlag != null && managerFlag.equals(Constant.MANAGER_FLAG_YES)){
                        SysOrgInfo orgInfo = cdacscontrolmgrRpc.getOrgByUserId(projectInfo.getUserId());
                        if(orgInfo != null){
                            List<OptionItem> userVOList = cdacscontrolmgrRpc.getUsersByOrgId(orgInfo.getOrgId());
                            Session session;
                            for (OptionItem user : userVOList){
                                String userId = user.getId();
                                session = clients.get(userId);
                                if(session != null && session.isOpen()){
                                    sendMsg(session,projectId,carNumber,type, picturePath, isComeIn,recordId,orderId);
                                }
                            }
                        }
                    }else{
                        List<OptionItem> userVOList = cdacscontrolmgrRpc.getUsersByOrgId(projectInfo.getOrganId());
                        Session session;
                        for (OptionItem user : userVOList){
                            String userId = user.getId();
                            session = clients.get(userId);
                            if(session != null && session.isOpen()){
                                sendMsg(session,projectId,carNumber,type, picturePath, isComeIn,recordId,orderId);
                            }
                        }
                    }
                    if (isComeIn) {
                        // 进场生成订单
                        log.info("进场生成订单");
                        order.setId(orderId);
                        order.setCarNum(carNumber);
                        order.setOrderId(System.currentTimeMillis() + "");
                        order.setParkRecordId(recordId);
                        order.setCreatedTime(LocalDateTime.now());
                        order.setEnterTime(LocalDateTime.now());
                        // 交易状态1.未缴费2.已缴费3.退款
                        order.setDealStatus(Constant.DEAL_STATUS_UNPAYED);
                        // 是否删除  1.删除 2.不删除
                        order.setIsDel(Constant.ORDER_UNDELETED);
                        order.setOrderFrom(Constant.ORDER_FROM_ACS);
//                                if(!hasPassRecord("出",projectId,serialNum,carInfo,carNum)){
//                                    log.error("车牌号[{}]没有出场记录",carNum);
//                                    transactionManager.rollback(transaction);
//                                    return JsonResult.error("车牌号["+carNum+"]没有出场记录");
//                                }
                        // 查询是否是免费车或包时车，免费车或包时车不生成订单
                        if (carInfo != null || isBaoshiChe) {
                            order.setOrderAmount((double) Constant.NUM_ZERO);
                            order.setDealStatus(Constant.DEAL_STATUS_PAYED);//免费或包时车设置为已缴费
                            order.setTotalOrderAmount((double) Constant.NUM_ZERO);
                            order.setOrderFrom(Constant.ORDER_FROM_CCBS);
                            cdacscontrolmgrOrderInfoService.save(order,true);
                            log.info("免费车或包时车进入");
                            String carType = Constant.CAR_TYPE_RENT;
                            sendMsgToScreen(clients,barrierId,Constant.SCREEN_STATUS_BUSY,true,carType,
                                    carNumber,surplusCarNum,Constant.ZERO,Constant.ZERO,serialNum);
                            log.info("门禁进场抬杆");
                            ScheduledFuture<JsonResult> schedule =
                                    executorService.schedule(new TaiganCallable(serialNum), Constant.NUM_TWO, TimeUnit.SECONDS);
                            JsonResult jsonResult2 = null;
                            try {
                                jsonResult2 = schedule.get();
                            } catch (InterruptedException | ExecutionException e) {
                                transactionManager.rollback(transaction);
                                e.printStackTrace();
                            }
                            // JsonResult jsonResult2 = taigan(serialNum);
                            if (jsonResult2 != null && jsonResult2.getSuccess()) {
                                // 发送进场通知
                                log.info("抬杆成功,免费车或包时车发送进场通知");
                                sendRcMsg(yardName, carNumber);
                                // 更新车场的剩余停车位数量
                                int freePlatNum = Constant.NUM_ZERO;
                                if(surplusCarNum > Constant.NUM_ZERO && surplusCarNum-Constant.NUM_ONE <= carNum){
                                    freePlatNum = surplusCarNum-Constant.NUM_ONE;
                                    newProjectInfo.setSurplusCarNum(surplusCarNum-Constant.NUM_ONE);
                                    cdacscontrolmgrProjectService.saveOrUpdate(newProjectInfo);
                                }
                                transactionManager.commit(transaction);
                                // 回到无车空闲状态
                                String finalBarrierId1 = barrierId;
                                int finalFreePlatNum = freePlatNum;
                                executorService.schedule(() -> {
                                    //回到无车空闲状态
                                    sendMsgToScreen(clients, finalBarrierId1,Constant.SCREEN_STATUS_FREE,true,carType,
                                            "", finalFreePlatNum,Constant.ZERO,Constant.ZERO,serialNum);
                                }, Constant.NUM_FIVE, TimeUnit.SECONDS);
                                updateYwp(projectId,freePlatNum);
                            } else {
                                log.info("免费车或包时车进场,抬杆失败");
                                transactionManager.rollback(transaction);
                            }
                            return JsonResult.ok("success");
                        }
                        log.info("临时车进入");
                        sendMsgToScreen(clients,barrierId,Constant.SCREEN_STATUS_BUSY,true,Constant.CAR_TYPE_TEMP,
                                carNumber,surplusCarNum,Constant.ZERO,Constant.ZERO,serialNum);

                        JsonResult saveResult = cdacscontrolmgrOrderInfoService.save(order,true);
                        if (saveResult.getSuccess()) {
                            // 抬竿
                            // 现在对应的输出 IO编号不确定，需要现场确认
                            //JsonResult jsonResult2 = taigan(serialNum);
                            ScheduledFuture<JsonResult> schedule =
                                    executorService.schedule(new TaiganCallable(serialNum), Constant.NUM_TWO, TimeUnit.SECONDS);
                            JsonResult jsonResult2 = null;
                            try {
                                jsonResult2 = schedule.get();
                            } catch (InterruptedException | ExecutionException e) {
                                transactionManager.rollback(transaction);
                                e.printStackTrace();
                            }
                            if (jsonResult2 != null && jsonResult2.getSuccess()) {
                                // 发送进场通知
                                log.info("进场抬杆成功,发送进场通知");
                                sendRcMsg(yardName, carNumber);
                                int freePlatNum = Constant.NUM_ZERO;
                                if(surplusCarNum > Constant.NUM_ZERO){
                                    freePlatNum = surplusCarNum-Constant.NUM_ZERO;
                                    newProjectInfo.setSurplusCarNum(freePlatNum);
                                    cdacscontrolmgrProjectService.saveOrUpdate(newProjectInfo);
                                }
                                transactionManager.commit(transaction);
                                // 5秒后回到空闲状态
                                int finalFreePlatNum = freePlatNum;
                                String finalBarrierId2 = barrierId;
                                executorService.schedule(() -> sendMsgToScreen(clients,finalBarrierId2,Constant.SCREEN_STATUS_FREE,true,Constant.CAR_TYPE_TEMP,
                                        "", finalFreePlatNum,Constant.ZERO,Constant.ZERO,serialNum), Constant.NUM_FIVE, TimeUnit.SECONDS);
                                updateYwp(projectId,freePlatNum);
                            } else {
                                log.info("进场抬杆失败,回滚事务");
                                transactionManager.rollback(transaction);
                            }
                        }
                    } else { //出场
                        cdacscontrolmgrRedisUtil.set(serialNum,picturePath);
                        // 看是否有入场记录,没有入场的记录的需要云坐席纠正车牌
//                        if (!hasPassRecord("进", projectId, serialNum, carInfo, carNumber)) {
//                            log.error("车牌号[{}]没有进场记录", carNumber);
//                            sendMsgToScreen(clients,barrierId,Constant.SCREEN_STATUS_BUSY,false,Constant.CAR_TYPE_RGQR,
//                                    carNumber,surplusCarNum,Constant.ZERO,Constant.ZERO,serialNum);
//                            transactionManager.rollback(transaction);
//                            return JsonResult.error("车牌号[" + carNumber + "]没有进场记录");
//                        }
                        // 查看是否是无费用车辆
                        String domain = cdacscontrolmgrRpc.getDomain();
                        String carType = isBaoshiChe ? Constant.CAR_TYPE_RENT : Constant.CAR_TYPE_TEMP;
                        HashMap param4 = new HashMap();
                        param4.put("yardId", projectId);
                        CdyardmgrChargeConfig chargeConfig = cdacscontrolmgrChargeConfigService.selectOne(param4);
                        if (carInfo == null && !isBaoshiChe && chargeConfig != null && !Constant.FRRR_CHARGE_RULE_ID.equals(chargeConfig.getRuleId())) {
                            HashMap param5 = new HashMap();
                            param5.put("ruleId", chargeConfig.getRuleId());
                            param5.put("ruleType",Constant.RULE_TYPE_TEMP);//1.临停收费规则
                            CdfinanmodRuledetail ruledetail = cdacscontrolmgrRuledetailMapper.selectOne(param5);
                            if (ruledetail != null) {
                                HashMap param6 = new HashMap();
                                //param6.put("orderFrom", Constant.ORDER_FROM_ACS);
                                param6.put("proId", projectId);
                                param6.put("carNum", carNumber);
                                param6.put("dealStatus", Constant.DEAL_STATUS_PAYED);
                                param6.put("isDel", Constant.ORDER_UNDELETED);
                                param6.put("outTimeIsNull",true);//出场时间为空，表示未出场
                                CdfinanmodOrder cdfinanmodOrder = cdacscontrolmgrOrderInfoService.selectOne(param6);
                                if (cdfinanmodOrder != null && cdfinanmodOrder.getPayTime() != null) {
                                    LocalDateTime payTime = cdfinanmodOrder.getPayTime();
                                    long minitues = DateUtil.getMinituesFromDateTime(payTime);
                                    int timeLimit = ruledetail.getTimeLimit();
                                    if (minitues > timeLimit) {
                                        // 事务回滚,不生成通行记录
                                        transactionManager.rollback(transaction);
                                        CdfinanmodOrder newOrder = new CdfinanmodOrder();
                                        BeanUtils.copyProperties(order, newOrder);
                                        String newOrderId = StringUtil.getUuid();
                                        newOrder.setId(newOrderId);
                                        newOrder.setCarNum(carNumber);
                                        newOrder.setOrderId(System.currentTimeMillis() + "");
                                        newOrder.setParkRecordId(recordId);
                                        newOrder.setCreatedTime(LocalDateTime.now());
                                        newOrder.setEnterTime(DateUtil.getNextMinTime(payTime, timeLimit));
                                        // 交易状态1.未缴费2.已缴费3.退款
                                        newOrder.setDealStatus(Constant.DEAL_STATUS_UNPAYED);
                                        // 是否删除  1.删除 2.不删除
                                        newOrder.setIsDel(Constant.ORDER_UNDELETED);
                                        DefaultTransactionDefinition def2 = new DefaultTransactionDefinition();
                                        def2.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
                                        TransactionStatus transaction2 = transactionManager.getTransaction(def2);
                                        cdacscontrolmgrOrderInfoService.save(newOrder,true);
                                        log.info("[门禁]超过了缴费出场后限时,生成新订单");
                                        transactionManager.commit(transaction2);
                                        saveToRedis(serialNum,newOrderId);
                                        CarOrderInfo carOrderInfo = queryCarOrder(domain, projectId, carNumber);
                                        String parkTime = carOrderInfo != null ? carOrderInfo.getParkTime() : Constant.ZERO;
                                        String amout = carOrderInfo != null ? carOrderInfo.getOrderAmount() : Constant.ZERO;
                                        sendMsgToScreen(clients,barrierId,Constant.SCREEN_STATUS_BUSY,false,Constant.CAR_TYPE_QJF,
                                                carNumber,surplusCarNum,parkTime,amout,serialNum);
                                        return JsonResult.error("此车有未缴费的订单");
                                    }
                                }
                            }
                            // 查询是否缴费
                            HashMap param3 = new HashMap();
                            //param3.put("orderFrom", Constant.ORDER_FROM_ACS);
                            param3.put("proId", projectId);
                            param3.put("carNum", carNumber);
                            param3.put("dealStatus", Constant.DEAL_STATUS_UNPAYED);
                            param3.put("isDel", Constant.ORDER_UNDELETED);
                            param3.put("morethan0", "true");
                            List<CdfinanmodOrder> orderList = cdacscontrolmgrOrderInfoService.list(param3);
                            if (orderList.size() > 0) {
                                log.info("此车有未缴费的订单");
                                saveToRedis(serialNum,orderList.get(0).getId());
                                CarOrderInfo carOrderInfo = queryCarOrder(domain, projectId, carNumber);
                                String parkTime = carOrderInfo != null ? carOrderInfo.getParkTime() : Constant.ZERO;
                                String amout = carOrderInfo != null ? carOrderInfo.getOrderAmount() : Constant.ZERO;
                                sendMsgToScreen(clients,barrierId,Constant.SCREEN_STATUS_BUSY,false,carType,
                                        carNumber,surplusCarNum,parkTime,amout,serialNum);
                                return JsonResult.error("此车有未缴费的订单");
                            }
                        }
                        CarOrderInfo carOrderInfo = queryCarOrder(domain, projectId, carNumber);
                        String parkTime = carOrderInfo != null ? carOrderInfo.getParkTime() : Constant.ZERO;
                        if(!Constant.CAR_TYPE_TEMP.equals(carType)){
                            LocalDateTime enterTime = queryComenInTime(projectId, serialNum,carInfo, carNumber);
                            long differMin = DateUtil.getDifferMin(enterTime, LocalDateTime.now());
                            parkTime = DateUtil.getDifferTime(differMin);
                        }
                        String amout = carOrderInfo != null ? carOrderInfo.getOrderAmount() : Constant.ZERO;
                        sendMsgToScreen(clients,barrierId,Constant.SCREEN_STATUS_BUSY,false,carType,
                                carNumber,surplusCarNum,parkTime,amout,serialNum);
                        log.info("门禁出场抬杆");
                        //JsonResult jsonResult2 = taigan(serialNum);
                        ScheduledFuture<JsonResult> schedule =
                                executorService.schedule(new TaiganCallable(serialNum), Constant.NUM_TWO, TimeUnit.SECONDS);
                        JsonResult jsonResult2 = null;
                        try {
                            jsonResult2 = schedule.get();
                        } catch (InterruptedException | ExecutionException e) {
                            transactionManager.rollback(transaction);
                            e.printStackTrace();
                        }
                        if (jsonResult2.getSuccess()) {
                            // 发送出场通知
                            log.info("抬杆成功,发送出场通知");
                            sendCcMsg(yardName, carNumber);
                            // 更新车场的剩余停车位数量
                            int freePlatNum = Constant.NUM_ZERO;
                            if(surplusCarNum+Constant.NUM_ONE <= carNum){
                                freePlatNum = surplusCarNum+Constant.NUM_ONE;
                                newProjectInfo.setSurplusCarNum(freePlatNum);
                                cdacscontrolmgrProjectService.saveOrUpdate(newProjectInfo);
                            }
                            // 订单表设置OUT_TIME出场时间
                            HashMap param3 = new HashMap();
                            param3.put("proId",projectId);
                            param3.put("carNum",carNumber);
                            param3.put("dealStatus",Constant.DEAL_STATUS_PAYED);
                            param3.put("isDel",Constant.ORDER_UNDELETED);
                            param3.put("outTimeIsNull",true);
                            CdfinanmodOrder cdfinanmodOrder = cdacscontrolmgrOrderInfoService.selectOne(param3);
                            if(cdfinanmodOrder != null){
                                CdfinanmodOrder orderNew = new CdfinanmodOrder();
                                orderNew.setId(cdfinanmodOrder.getId());
                                orderNew.setOutTime(LocalDateTime.now());
                                cdacscontrolmgrOrderInfoService.save(orderNew,false);
                            }
                            //移除场内车辆
                            removeCarInside(carNumber,projectId);
                            transactionManager.commit(transaction);
                            String finalBarrierId = barrierId;
                            int finalFreePlatNum = freePlatNum;
                            executorService.schedule(() -> sendMsgToScreen(clients, finalBarrierId,Constant.SCREEN_STATUS_FREE,false,"",
                                    "", finalFreePlatNum,Constant.ZERO,Constant.ZERO,serialNum), Constant.NUM_FIVE, TimeUnit.SECONDS);
                            updateYwp(projectId,freePlatNum);
                        } else {
                            log.info("抬杆失败,回滚事务");
                            transactionManager.rollback(transaction);
                        }

                    }
                    log.info("[门禁项目管理]车牌号(" + (carNumber) + ")识别通过");
                    return jsonResult;
                }
            }
        } else if (Constant.CMD_NAME_SNAPSHOT_DATA_PUSH.equals(cmdName)) { //人脸识别
            log.info("门禁管理人脸识别上报: " + upDataStr);
            // 现在只返回r1(人员编号,就是传进去的人员ID),r2(人员名称,显示都是-,)
            String personId = "";
            // 协议修改之后返回r1(图片),r2(人员编号,就是传进去的人员ID),r3(人员名称,显示都是-,)
            String base64PicInfo = reportMessage.getString("r1");//base64图片
            if(base64PicInfo.startsWith("data:image/")){
                base64PicInfo = "data:image/jpeg;base64," + base64PicInfo;
            }
            personId = reportMessage.getString("r2");
            String personName = reportMessage.getString("r3");
            if (!StringUtils.isEmpty(personId)) {
                CdparkmanagerProjectAccess projectAccess = queryProjectAccess(serialNum);
                String acsName = null, projectId = null;
                if (projectAccess != null) {
                    acsName = projectAccess.getAccessName();
                    projectId = projectAccess.getProjectId();
                }
                CdacscontrolmgrOwner ownerInfo = ownerMapper.selectByKey(personId);
                if (ownerInfo != null) { //说明是业主
                    CdacscontrolmgrPersonRecord personRecord = new CdacscontrolmgrPersonRecord();
                    personRecord.setOpenUser(ownerInfo.getName());
                    personRecord.setOpenUserSf("业主");
                    personRecord.setPhone(ownerInfo.getPhone());
                    personRecord.setAcsName(acsName);
                    personRecord.setOpenType("人脸识别");
                    personRecord.setOpenTime(localDateTime);
                    personRecord.setProjectId(projectId);
                    personRecord.setPicture(base64PicInfo);
                    personRecordService.saveOrUpdate(personRecord);
                } else { // 访客
                    CdacscontrolmgrVisitorRecord visitorRecord = new CdacscontrolmgrVisitorRecord();
                    // 查询访客登记表
                    CdacscontrolmgrRegistInfo registInfo = registInfoMapper.selectByKey(personId);
                    if (registInfo != null) {
                        visitorRecord.setOwner(registInfo.getOwnerName());
                        visitorRecord.setPhone(registInfo.getOwnerPhone());
                        visitorRecord.setVisitor(registInfo.getVisitorName());
                        String visitTime = registInfo.getVisitDate() + " " + registInfo.getComeinTime() + " - " + registInfo.getLeaveTime();
                        visitorRecord.setVisitTime(visitTime);
                        visitorRecord.setAcsName(acsName);
                        visitorRecord.setOpenTime(localDateTime);
                        visitorRecord.setFacePicture(base64PicInfo);
                        visitorRecord.setProjectId(projectId);
                        visitorRecordService.saveOrUpdate(visitorRecord);
                        // 更改访客记录的状态为 已来访
                        registInfo.setStatus(Constant.REGIST_INFO_STATUS_FINISHED);
                        registInfo.setVisitTime(LocalDateTime.now());
                        registInfoMapper.updateByKey(registInfo);
                    }
                }
            }
        }else if(Constant.CMD_NAME_CARD_SWIPING_RECORD.equalsIgnoreCase(cmdName)){
            log.info("密码输入上报: " + upDataStr);
            CdparkmanagerProjectAccess projectAccess = queryPwdAccess(serialNum);
            if(projectAccess != null){
                String r5Str = reportMessage.getString("r5");//输入的密码是逗号隔开的16进制
                String pwd = NumConvertUtil.hexStr2Str(r5Str.replaceAll(" ",""));
                HashMap param = new HashMap();
                String encryptedPwd = AESUtil.encrypt(pwd, Constant.ENCRYPT_KEY);
                param.put("tempPwd", encryptedPwd);
                param.put("projectId", projectAccess.getProjectId());
                param.put("visitDate", DateUtil.getCurrentDayYMD("yyyy-MM-dd"));
                CdacscontrolmgrRegistInfo registInfo = registInfoMapper.selectOne(param);
                if(registInfo == null){
                    String event = StringUtil.chineseToGB2312(Constant.ERROE_PWD,Constant.NUMBER_32);
                    cdacscontrolmgrRpc.responseCardSwipingRecord(false,serialNum,event);
                    String msg = "密码错误或该时段没有访客登记记录";
                    log.error(msg);
                    return JsonResult.error(msg);
                }
                String key = registInfo.getId();
                boolean hasKey = cdacscontrolmgrRedisUtil.hasKey(key);
                if(!hasKey){
                    log.error("密码已失效");
                    String event = StringUtil.chineseToGB2312(Constant.INVALID_PWD,Constant.NUMBER_32);
                    cdacscontrolmgrRpc.responseCardSwipingRecord(false,serialNum,event);
                    return JsonResult.error("密码已失效");
                }
                String tempPwd = cdacscontrolmgrRedisUtil.get(key);
                if(encryptedPwd.equals(tempPwd)){//密码正确，手动开门
                    //cdacscontrolmgrRpc.openDoor(serialNum);
                    log.info("密码正确，手动开门");
                    String event = StringUtil.chineseToGB2312(Constant.CORRECT_PWD,Constant.NUMBER_32);
                    JsonResult jsonResult = cdacscontrolmgrRpc.responseCardSwipingRecord(true, serialNum, event);
                    if(jsonResult.getSuccess()){
                        CdacscontrolmgrVisitorRecord visitorRecord = new CdacscontrolmgrVisitorRecord();
                        visitorRecord.setOwner(registInfo.getOwnerName());
                        visitorRecord.setPhone(registInfo.getOwnerPhone());
                        visitorRecord.setVisitor(registInfo.getVisitorName());
                        String visitTime = registInfo.getVisitDate() + " " + registInfo.getComeinTime() + " - " + registInfo.getLeaveTime();
                        visitorRecord.setVisitTime(visitTime);
                        visitorRecord.setAcsName(projectAccess.getAccessName());
                        visitorRecord.setOpenTime(localDateTime);
                        visitorRecord.setProjectId(registInfo.getProjectId());
                        visitorRecordService.saveOrUpdate(visitorRecord);
                        // 更改访客记录的状态为 已来访
                        registInfo.setStatus(Constant.REGIST_INFO_STATUS_FINISHED);
                        registInfo.setVisitTime(LocalDateTime.now());
                        registInfoMapper.updateByKey(registInfo);
                    }
                }
                String event = StringUtil.chineseToGB2312(Constant.ERROE_PWD,Constant.NUMBER_32);
                cdacscontrolmgrRpc.responseCardSwipingRecord(false,serialNum,event);
            }
        }
        return JsonResult.error(upDataStr);
    }

    // 判断车辆是否在场内,在场内不允许进入
    private boolean isCarInside(String carNumber, String projectId){
        HashMap param = new HashMap();
        param.put("carNumber",carNumber);
        param.put("projectId",projectId);
        param.put("isDel",Constant.IS_DEL_NO);//未删除
        CdyardmgrCarInside carInside = carInsideMapper.selectOne(param);
        return carInside != null;
    }

    private void saveToRedis(String mac,String orderId){
        cdacscontrolmgrRedisUtil.set(Constant.ORDER_NUM+mac,orderId);
    }

    private void sendMsgToScreen(Map<String, Session> clients,String barrierId,String status,boolean isComeIn,
                                 String carType,String carNumber,int freeCarNum,String parkTime,String amout,String mac){
        log.info("通过道闸查询LED的配置");
        HashMap param = new HashMap();
        param.put("barrierId",barrierId);
        CdyardmgrProjectLed projectLed = projectLedMapper.selectOne(param);
        if(projectLed != null && !StringUtil.isEmpty(projectLed.getLedMac())){
            String projectId = projectLed.getProjectId();
            param.put("ledId",projectLed.getId());
            CdyardmgrProjectLedContent ledContent = projectLedContentMapper.selectOne(param);
            if(ledContent != null){
                String ledMac = projectLed.getLedMac();
                if(Constant.SCREEN_STATUS_FREE.equals(status)){
                    cdacscontrolmgrRpc.showLedForFree(ledContent,freeCarNum,ledMac);
                }else {
                    cdacscontrolmgrRpc.showLedForBusy(ledContent,freeCarNum,parkTime,amout,isComeIn,carType,carNumber,ledMac,projectId,mac);
                }
            }
        }
        log.info("通过道闸查询LCD的配置");
        CdyardmgrProjectLcd projectLcd = projectLcdMapper.selectOne(param);
        if(projectLcd != null){
            param.put("lcdId",projectLcd.getId());
            CdyardmgrProjectLcdContent lcdContent = projectLcdContentMapper.selectOne(param);
            if(lcdContent != null){
                Session session = clients.get(barrierId);
                if(session != null && session.isOpen()){
                    JSONObject msgObj = new JSONObject();
                    msgObj.put("purpose","lcd");//标识 lcd消息
                    msgObj.put("status",status);//状态busy忙碌 free空闲
                    msgObj.put("isComeIn",isComeIn);//是否是进口true是false否
                    msgObj.put("carType",carType);//车辆类型
                    msgObj.put("carNumber",carNumber);//车牌号
                    msgObj.put("freeCarNum",freeCarNum);//余位
                    msgObj.put("parkTime",parkTime);//停车时长(分钟)
                    msgObj.put("amout",amout);//停车费金额(元)
                    String domain = cdacscontrolmgrRpc.getDomain();
                    String projectId = projectLcd.getProjectId();
                    boolean isHttps = !StringUtil.isEmpty(domain) && domain.startsWith(Constant.HTTPS_SCHEME);
                    String url = Constant.QECODE_PAY_URL + "?carNum="+carNumber+"&proId="+projectId+"&mac="+mac;
                    String qrCodeUrl = null;
                    try {
                        HttpClientResult httpClientResult = HttpClientPoolUtil.doGet(url, isHttps);
                        String content = httpClientResult.getContent();
                        if(content != null){
                            JsonResult jsonResult1 = JSONObject.parseObject(content, JsonResult.class);
                            if(jsonResult1.getSuccess() && jsonResult1.getData() != null){
                                JSONObject jsonObj = JSONObject.parseObject(jsonResult1.getData().toString());
                                qrCodeUrl = jsonObj.getString("addr");
                            }
                        }
                    } catch (Exception e) {
                        log.error("获取付款二维码出错: " + e.toString());
                    }
                    msgObj.put("qrCodeUrl",qrCodeUrl);//二维码地址
                    msgObj.put("lcdContent",lcdContent);//lcd显示内容
                    synchronized (session){
                        session.getAsyncRemote().sendText(msgObj.toJSONString());
                    }
                }
            }
        }
    }

    private void updateYwp(String projectId, int freeCarNum) {
        HashMap param = new HashMap();
        param.put("projectId",projectId);
        List<CdyardmgrProjectYwp> list = projectYwpMapper.list(param);
        for (CdyardmgrProjectYwp ywp : list){
            String mac = ywp.getYwpMac();
            if(StringUtil.isEmpty(mac)){continue;}
            cdacscontrolmgrRpc.showYwp(Constant.YWP_LINE_ONE,freeCarNum,mac);
        }
    }

    private CarOrderInfo queryCarOrder(String domain, String projectId, String carNumber){
        try {
            String url = domain + Constant.QUERY_ORDER_URL+"?proId="+projectId+"&carNum="+carNumber;
            HttpClientResult httpClientResult = HttpClientPoolUtil.doGet(url, false);
            String content = httpClientResult.getContent();
            if(content != null){
                JsonResult jsonResult1 = JSONObject.parseObject(content, JsonResult.class);
                if(jsonResult1.getSuccess() && jsonResult1.getData() != null){
                    return JSONObject.parseObject(jsonResult1.getData().toString(), CarOrderInfo.class);

                }
            }
        } catch (Exception e) {
            log.error(e.toString());
        }
        return null;
    }

    private CdparkmanagerProjectAccess queryProjectAccess(String serialNum) {
        HashMap param = new HashMap();
        param.put("faceMac", serialNum);
        CdparkmanagerProjectAccess projectAccess = projectAccessService.selectOne(param);
        return projectAccess;
    }
    private CdparkmanagerProjectAccess queryPwdAccess(String serialNum) {
        HashMap param = new HashMap();
        param.put("passwordMac", serialNum);
        CdparkmanagerProjectAccess projectAccess = projectAccessService.selectOne(param);
        return projectAccess;
    }

    private boolean hasPassRecord(String direction, String projectId, String serialNum, CdyardmgrCarInfo carInfo, String carNum) {
        HashMap paramP = new HashMap();
        paramP.put("carNo", carNum);
        paramP.put("direction", direction);
        paramP.put("yardId", projectId);
        paramP.put("projectId", projectId);
        paramP.put("mac", serialNum);
        CdacscontrolmgrCarRecord carRecord1 = null;
        CdacscontrolmgrCxlfRecord cxlfRecord = null;
        if (carInfo != null) { //业主或物业进入
            carRecord1 = carRecordService.selectOne(paramP);
        } else {
            cxlfRecord = cxlfRecordService.selectOne(paramP);
        }
        return carRecord1 != null || cxlfRecord != null;
    }

    private LocalDateTime queryComenInTime(String projectId, String serialNum, CdyardmgrCarInfo carInfo, String carNum){
        HashMap paramP = new HashMap();
        paramP.put("carNo", carNum);
        paramP.put("direction", "进");
        paramP.put("yardId", projectId);
        paramP.put("projectId", projectId);
        paramP.put("mac", serialNum);
        if (carInfo != null) { //业主或物业进入
            CdacscontrolmgrCarRecord carRecord = carRecordService.selectOne(paramP);
            return carRecord != null ? carRecord.getPassTime() : null;
        } else {
            CdacscontrolmgrCxlfRecord cxlfRecord = cxlfRecordService.selectOne(paramP);
            return cxlfRecord != null ? cxlfRecord.getPassTime() : null;
        }
    }

    private boolean isFreeCar(String projectId, String carNum) {
        if(StringUtil.isEmpty(carNum)){return false;}
        HashMap param1 = new HashMap();
        param1.put("flag", Constant.SCREEN_STATUS_FREE);
        param1.put("yardId", projectId);
        param1.put("province", carNum.substring(0,1));
        param1.put("carNo", carNum.substring(1));
        CdyardmgrCarInfo cdyardmgrCarInfo = carInfoService.selectOne(param1);
        return cdyardmgrCarInfo != null;
    }

    private void sendCcMsg(String yardName, String carNum) {
        JSONObject msgJson = new JSONObject();
        JSONObject titleJson = new JSONObject();
        titleJson.put("value", "您的爱车已驶离停车场");
        titleJson.put("color", "#173177");
        msgJson.put("first", titleJson);
        JSONObject locationJson = new JSONObject();
        locationJson.put("value", yardName);//停车场
        locationJson.put("color", "#173177");
        msgJson.put("keyword1", locationJson);
        JSONObject carNumJson = new JSONObject();
        carNumJson.put("value", carNum);//车牌号
        carNumJson.put("color", "#173177");
        msgJson.put("keyword2", carNumJson);
        JSONObject remarkJson = new JSONObject();
        remarkJson.put("value", "欢迎下次光临！");
        remarkJson.put("color", "#173177");
        msgJson.put("remark", remarkJson);
        List<String> openIds = getOpenIds(carNum);
        if (openIds.size() > 0) {
            String templateId = getTemplateId(Constant.TITLE_TYPE_EXIT);
            for (String openId : openIds) {
                cdacscontrolmgrRpc.pushPaMsg(templateId, openId, msgJson.toJSONString());
            }
        }
    }

    private void sendRcMsg(String yardName, String carNum) {
        JSONObject msgJson = new JSONObject();
        JSONObject titleJson = new JSONObject();
        titleJson.put("value", "尊敬的车主，您好，您的车辆已入场");
        titleJson.put("color", "#173177");
        msgJson.put("first", titleJson);
        JSONObject carNumJson = new JSONObject();
        carNumJson.put("value", carNum);//车牌号
        carNumJson.put("color", "#173177");
        msgJson.put("keyword1", carNumJson);
        JSONObject locationJson = new JSONObject();
        locationJson.put("value", yardName);//停车场
        locationJson.put("color", "#173177");
        msgJson.put("keyword2", locationJson);
        JSONObject timeJson = new JSONObject();
        timeJson.put("value", df.format(LocalDateTime.now()));// 入场时间
        timeJson.put("color", "#173177");
        msgJson.put("keyword3", timeJson);
        JSONObject remarkJson = new JSONObject();
        remarkJson.put("value", "欢迎光临！祝您生活愉快！");
        remarkJson.put("color", "#173177");
        msgJson.put("remark", remarkJson);
        // 有可能是同一个车牌号被多个手机绑定
        List<String> openIds = getOpenIds(carNum);
        if (openIds.size() > 0) {
            String templateId = getTemplateId(Constant.TITLE_TYPE_ENTRANCE);
            for (String openId : openIds) {
                cdacscontrolmgrRpc.pushPaMsg(templateId, openId, msgJson.toJSONString());
            }
        }
    }

    private JsonResult taigan(String serialNum) {
        return cdacscontrolmgrRpc.ioctlResp(
                Constant.IOCTL_RESP_DELAYTIME, Constant.IOCTL_RESP_IOCODE, Constant.IOCTL_RESP_STATUSVALUE, serialNum);
    }

    private int countOrderMgt(String carNum, String projectNum){
        HashMap param = new HashMap();
        param.put("licensePlate", carNum);
        param.put("parkingProjectId", projectNum); //项目编号
        param.put("projectType", Constant.PROJECT_TYPE_ACS+""); //项目类型1车场2门禁3余额充值4余额支付
        return cdacscontrolmgrOrderMgtMapper.listPageCount(param);
    }

    private CdxmyyOrderMgt queryOrderMgt(String carNum, String projectNum){
        HashMap param = new HashMap();
        param.put("licensePlate", carNum);
        param.put("parkingProjectId", projectNum); //项目编号
        param.put("paymentStatus", Constant.IS_AUTHED); //1已支付
        param.put("projectType", Constant.PROJECT_TYPE_ACS+""); //项目类型1车场2门禁3余额充值4余额支付
        return cdacscontrolmgrOrderMgtMapper.selectOne(param);
    }

    private boolean isBaoshiChe(String carNum, String projectNum) {
        HashMap param = new HashMap();
        param.put("licensePlate", carNum);
        param.put("paymentStatus", Constant.IS_AUTHED); //1已支付
        param.put("parkingProjectId", projectNum); //项目编号
        param.put("projectType", Constant.PROJECT_TYPE_ACS+""); //项目类型1车场2门禁3余额充值4余额支付
        CdxmyyOrderMgt orderMgt = cdacscontrolmgrOrderMgtMapper.selectOne(param);
        return isValidTime(orderMgt);
    }

    private boolean isValidTime(CdxmyyOrderMgt orderMgt){
        if(orderMgt == null || orderMgt.getEndTime() == null){
            return false;
        }
        String timePeriod = orderMgt.getPacketTimePeriod();
        if(StringUtil.isEmpty(timePeriod)){return false;}
        String[] timePeriodArr = timePeriod.split("-");
        if(timePeriodArr.length < 2){return false;}
        LocalDateTime now = LocalDateTime.now();
        String dateStr = DateUtil.getDateTimeAsString(now, Constant.DATE_PATTERRN);
        LocalDateTime startTime =  DateUtil.timeString2LocalDateTime(
                dateStr + " " + timePeriodArr[0].trim(),DateUtil.DATE_TIME_PATTERRN);
        LocalDateTime endTime =  DateUtil.timeString2LocalDateTime(
                dateStr + " " + timePeriodArr[1].trim(),DateUtil.DATE_TIME_PATTERRN);
        boolean isNotFinished = now.isBefore(orderMgt.getEndTime());
        return isNotFinished && now.isAfter(startTime) && now.isBefore(endTime);
    }

    private List<String> getOpenIds(String carNo) {
        HashMap param = new HashMap();
        param.put("carNo", carNo);
        param.put("isDel", Constant.ORDER_UNDELETED);
        List<CdfinanmodUser> list = cdacscontrolmgrUserMapper.list(param);
        List<String> openIdList = new ArrayList<>();
        list.forEach(item -> {
            String mpOpenid = item.getMpOpenid();
            if (!StringUtil.isEmpty(mpOpenid)) {
                openIdList.add(mpOpenid);
            }
        });
        return openIdList;
    }

    private String getTemplateId(String titleType) {
        HashMap param = new HashMap();
        CdgzhpzNotice notice = cdacscontrolmgrNoticeMapper.selectOne(param);
        if(null == notice){return "";}
        switch (titleType){
            case Constant.TITLE_TYPE_ENTRANCE:return notice.getEnterTemplate();
            case Constant.TITLE_TYPE_PAY:return notice.getPayTemplate();
            case Constant.TITLE_TYPE_EXIT:return notice.getOutTemplate();
            default:return "";
        }
    }

    private void sendMsg(Session session,String projectId,String carNum,String type,String imgPath,boolean isComeIn,String recordId,String orderId){
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("projectId",projectId);
        jsonObject.put("carNum",carNum);
        jsonObject.put("type",type);
        jsonObject.put("time",DateUtil.getDateTimeAsString(LocalDateTime.now(),""));
        jsonObject.put("img",imgPath);
        jsonObject.put("purpose","lprReport");//车牌识别上报的标识
        jsonObject.put("isComeIn",isComeIn);//是否是入场
        jsonObject.put("recordId",recordId);
        jsonObject.put("orderId",orderId);
        String msg = jsonObject.toJSONString();
        synchronized (session){
            session.getAsyncRemote().sendText(msg);
        }
    }

    private void removeCarInside(String carNumber, String projectId) {
        HashMap param = new HashMap();
        param.put("carNumber",carNumber);
        param.put("projectId",projectId);
        param.put("isDel",Constant.IS_DEL_NO);//未删除
        CdyardmgrCarInside carInside = carInsideMapper.selectOne(param);
        if(carInside == null){return;}
        CdyardmgrCarInside carInsideNew = new CdyardmgrCarInside();
        long min = DateUtil.getDifferMin(carInsideNew.getEnterTime(), LocalDateTime.now());
        carInsideNew.setId(carInside.getId());
        carInsideNew.setStayTime(min);
        carInsideNew.setIsDel(Constant.IS_DEL_YES);
        carInsideNew.setRemark("正常出入场");
        carInsideMapper.updateByKey(carInsideNew);
    }

    class TaiganCallable implements Callable<JsonResult> {
        private String serialNum;

        public TaiganCallable(String serialNum) {
            this.serialNum = serialNum;
        }

        @Override
        public JsonResult call() {
            return taigan(serialNum);
        }
    }

}
